#include "Algorithm.h"
#include "openssl/des.h"

Algorithm::Algorithm()
{

}

QString Algorithm::fromBCD(QByteArray &data)
{
    QString buf;
    QByteArray id;

    id = data.left(16);
    id = id.toHex();

    buf = id;

    return buf.left(buf.indexOf('f'));
}

QByteArray Algorithm::toByte(QString num)
{
    QByteArray buf, str;
    struct bcd
    {
        uint8_t l:4;
        uint8_t h:4;
    }*bin;

    str = num.toLocal8Bit();
    buf.resize(num.size()/2);
    bin = (struct bcd*)buf.data();

    for (int i = 0; i < str.size(); i ++)
    {
        uint8_t tmp = str.at(i);

        if (tmp >= '0' && (tmp <= '9'))
        {
            tmp -= '0';
        }
        else if (tmp >= 'A' && (tmp <= 'F'))
        {
            tmp = tmp - 'A' + 10;
        }
        else
        {
            tmp = tmp - 'a' + 10;
        }

        if (i & 1)
        {
            bin[i/2].l = tmp;
        }
        else
        {
            bin[i/2].h = tmp;
        }
    }

    return buf;
}

QByteArray Algorithm::toBCD(QString num)
{
    QByteArray buf(16, 0xFF), str;
    struct bcd
    {
        uint8_t l:4;
        uint8_t h:4;
    }*id;

    id = (struct bcd*)buf.data();

    str = num.toLocal8Bit();
    for (int i = 0; i < str.size(); i ++)
    {
        uint8_t tmp = str.at(i) - '0';

        if (i & 1)
        {
            id[i/2].l = tmp;
        }
        else
        {
            id[i/2].h = tmp;
        }
    }

    return buf;
}

void Algorithm::calcKeyB(QString &cid, QByteArray &keyb)
{
    const_DES_cblock key1 = {0x12, 0xD6, 0xC5, 0xC0, 0xB8, 0x27, 0xE6, 0x0A};
    const_DES_cblock key2 = {0x9F, 0x34, 0x4D, 0xB9, 0x4B, 0xCF, 0x20, 0x39};
    const_DES_cblock d = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
    const_DES_cblock sekey1;
    const_DES_cblock sekey2;
    unsigned char out[8];
    DES_key_schedule ks1, ks2, ks3;
    QByteArray card;

    if (cid.isEmpty())
        return;

    cid = cid.right(16);
    card = cid.toLocal8Bit();

    DES_set_key_unchecked(&key1, &ks1);
    DES_set_key_unchecked(&key2, &ks2);
    DES_set_key_unchecked(&key1, &ks3);

    DES_ecb3_encrypt((const_DES_cblock*)&card.data()[0], &sekey1, &ks1, &ks2, &ks3, DES_ENCRYPT);
    DES_ecb3_encrypt((const_DES_cblock*)&card.data()[8], &sekey2, &ks1, &ks2, &ks3, DES_ENCRYPT);

    DES_set_key_unchecked(&sekey1, &ks1);
    DES_set_key_unchecked(&sekey2, &ks2);
    DES_set_key_unchecked(&sekey1, &ks3);

    DES_ecb3_encrypt(&d, (const_DES_cblock*)out, &ks1, &ks2, &ks3, DES_ENCRYPT);

    keyb.resize(6);
    memcpy(keyb.data(), &out[2], 6);
}
